package com.dasnzhuang.halo.security.config;

import java.util.Arrays;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.ClientTokenServices;
import org.springframework.security.oauth2.client.token.JdbcClientTokenServices;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;

import com.dasnzhuang.halo.security.support.CustomUserDetailsService;
import com.dasnzhuang.halo.security.support.LoginSuccessHandler;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    

    // http://localhost:8080/login 输入正确的用户名密码 并且选中remember-me 则登陆成功，转到 index页面
    // 再次访问index页面无需登录直接访问
    // 访问http://localhost:8080/home 不拦截，直接访问，
    // 访问http://localhost:8080/hello 需要登录验证后，且具备
    // “ADMIN”权限hasAuthority("ADMIN")才可以访问
    @Override
    protected void configure(HttpSecurity http) throws Exception {
     // @formatter:off
        http.authorizeRequests()
            .antMatchers("/authrole/**").hasRole("USER")
            .anyRequest().permitAll()
            .and()
        .logout()
            .logoutSuccessUrl("/home")
            .permitAll()
            .and()
        .formLogin()
            .loginProcessingUrl("/login")
            .loginPage("/login")
            .permitAll();
    // @formatter:on
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // 指定密码加密所使用的加密器为passwordEncoder()
        // 需要将密码加密后写入数据库
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
        auth.eraseCredentials(false);
    }
    
    

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(4);
    }

    @Bean
    public LoginSuccessHandler loginSuccessHandler() {
        return new LoginSuccessHandler();
    }
    
    @Configuration
    @EnableOAuth2Client
    protected static class ResourceConfiguration {
        
        @Value("${halo.frame.variables.accessTokenUri}")
        private String accessTokenUri;

        @Value("${halo.frame.variables.userAuthorizationUri}")
        private String userAuthorizationUri;
        
        @Autowired
        private DataSource dataSource;
        
        @Bean
        public OAuth2ProtectedResourceDetails role() {
            AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
            details.setId("halo/tonr");
            details.setClientId("tonr");
            details.setClientSecret("secret");
            details.setAccessTokenUri(accessTokenUri);
            details.setUserAuthorizationUri(userAuthorizationUri);
            details.setScope(Arrays.asList("read", "write"));
            return details;
        }
        
        @Bean
        public ClientTokenServices  clientTokenServices(){
            return new JdbcClientTokenServices(dataSource);
        }
        
        @Bean
        @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
        public OAuth2RestTemplate roleRestTemplate(OAuth2ClientContext clientContext,ClientTokenServices clientTokenServices) {
            OAuth2RestTemplate template = new OAuth2RestTemplate(role(), clientContext);
//            AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider()));
//            provider.setClientTokenServices(clientTokenServices());
//            template.setAccessTokenProvider(provider);
            return template;
        }
    }
}
